summaryrefslogtreecommitdiff
path: root/src/pages/blog/[...date].astro
diff options
context:
space:
mode:
Diffstat (limited to 'src/pages/blog/[...date].astro')
-rw-r--r--src/pages/blog/[...date].astro251
1 files changed, 109 insertions, 142 deletions
diff --git a/src/pages/blog/[...date].astro b/src/pages/blog/[...date].astro
index 1742baa..d66ac8e 100644
--- a/src/pages/blog/[...date].astro
+++ b/src/pages/blog/[...date].astro
@@ -1,161 +1,128 @@
---
import type {
- GetStaticPaths,
InferGetStaticParamsType,
InferGetStaticPropsType,
} from "astro";
-import { getCollection } from "astro:content";
import Base from "@layouts/Base.astro";
import DateSelector from "@components/DateSelector.astro";
-import BlogCard from "@components/BlogCard.astro";
-import { sortLastCreated } from "@lib/collection/helpers";
+import SimplePostList from "@components/templates/SimplePostList.astro";
+import { datePaths, sortLastCreated } from "@lib/collection/helpers";
-export const getStaticPaths = (async () => {
- const posts = await getCollection("blog");
-
- const archive = {
- years: new Set<number>(),
- monthsByYear: new Map<string, Set<number>>(),
- daysByMonth: new Map<string, Set<number>>(),
- postsByDate: new Map<string, typeof posts>(),
- sortedDates: [] as string[],
- };
-
- const getYMD = (date: Date) => {
- const y = date.getFullYear();
- const m = date.getMonth() + 1;
- const d = date.getDate();
- return { y, m, d };
- };
-
- for (const post of posts) {
- const { y, m, d } = getYMD(post.data.dateCreated);
-
- archive.years.add(y);
-
- if (!archive.monthsByYear.has(y.toString())) {
- archive.monthsByYear.set(y.toString(), new Set());
- }
- archive.monthsByYear.get(y.toString())!.add(m);
-
- const ym = `${y}/${String(m).padStart(2, "0")}`;
- if (!archive.daysByMonth.has(ym)) archive.daysByMonth.set(ym, new Set());
- archive.daysByMonth.get(ym)!.add(d);
-
- const ymd = `${ym}/${String(d).padStart(2, "0")}`;
- if (!archive.postsByDate.has(ymd)) archive.postsByDate.set(ymd, []);
- archive.postsByDate.get(ymd)!.push(post);
- }
-
- archive.sortedDates = Array.from(archive.postsByDate.keys()).sort();
-
- const paths = [];
-
- const sortedYears = Array.from(archive.years).sort();
-
- const lastYear = Math.max(...sortedYears.map(Number));
- paths.push({
- params: { year: undefined },
- props: {
- posts: posts.filter((p) =>
- p.data.dateCreated.getFullYear() === lastYear
- ),
- next: undefined,
- previous: sortedYears?.[sortedYears.length - 2],
- years: sortedYears,
- months: Array.from(archive.monthsByYear.get(lastYear.toString()) ?? []),
- },
- });
-
- for (const y of sortedYears) {
- const yearPosts = posts.filter((p) =>
- p.data.dateCreated.getFullYear() === Number(y)
- );
- const idx = sortedYears.indexOf(y);
- paths.push({
- params: { year: y },
- props: {
- posts: yearPosts,
- next: sortedYears?.[idx + 1],
- previous: sortedYears?.[idx - 1],
- years: sortedYears,
- months: Array.from(archive.monthsByYear.get(y.toString()) ?? []),
- },
- });
- }
-
- const allMonths = Array.from(archive.monthsByYear.entries())
- .flatMap(([year, mset]) =>
- Array.from(mset).map((m) => `${year}/${String(m).padStart(2, "0")}`)
- )
- .sort();
-
- for (const [y, months] of archive.monthsByYear) {
- const sortedMonths = Array.from(months).sort();
- for (const m of sortedMonths) {
- const monthPosts = posts.filter((p) => {
- const d = p.data.dateCreated;
- return (
- d.getFullYear() === Number(y) &&
- d.getMonth() + 1 === m
- );
- });
-
- const ym = `${y}/${String(m).padStart(2, "0")}`;
- const idx = allMonths.indexOf(ym);
-
- paths.push({
- params: { year: ym },
- props: {
- posts: monthPosts,
- next: allMonths?.[idx + 1],
- previous: allMonths?.[idx - 1],
- years: sortedYears,
- months: Array.from(months).sort(),
- days: Array.from(archive.daysByMonth.get(ym) ?? []).sort(),
- },
- });
- }
- }
-
- for (let i = 0; i < archive.sortedDates.length; i++) {
- const ymd = archive.sortedDates[i];
- const [y, m] = ymd.split("/");
- paths.push({
- params: { year: ymd },
- props: {
- posts: archive.postsByDate.get(ymd) ?? [],
- next: archive.sortedDates?.[i + 1],
- previous: archive.sortedDates?.[i - 1],
- years: sortedYears,
- months: Array.from(archive.monthsByYear.get(y) ?? []).sort(),
- days: Array.from(archive.daysByMonth.get(`${y}/${m}`) ?? []).sort(),
- },
- });
- }
-
- return paths;
-}) satisfies GetStaticPaths;
+export const getStaticPaths = datePaths;
export type Params = InferGetStaticParamsType<typeof getStaticPaths>;
export type Props = InferGetStaticPropsType<typeof getStaticPaths>;
-const title = "Blog";
-const description = "Latest articles.";
-
let { posts, previous, next, years, months, days } = Astro.props;
posts = posts.sort(sortLastCreated);
-const date = posts[0].data.dateCreated as Date;
+
+const dateParts = Astro.params.date?.split("/").map(Number);
+const y = dateParts?.[0];
+const m = dateParts?.[1] ?? 1;
+const d = dateParts?.[2] ?? 3;
+const date = (y !== undefined) ? new Date(Date.UTC(y, m - 1, d)) : undefined;
+
+const format = date === undefined
+ ? undefined
+ : new Intl.DateTimeFormat("pt-PT", {
+ year: y === undefined ? undefined : "numeric",
+ month: dateParts?.[1] === undefined ? undefined : "long",
+ day: dateParts?.[2] === undefined ? undefined : "numeric",
+ }).format(date);
+const title = "Publicações" + (format !== undefined ? ` -- ${format}` : "");
+const description = "Ultímas publicações" +
+ (format !== undefined ? ` do dia ${format}` : "") + ".";
---
<Base {title} {description}>
- <main>
- <h2>Blogue</h2>
- {date && <DateSelector {date} {years} {months} {days} />}
- {posts.map((post) => <BlogCard {...post} />)}
- <div>
- {previous && <a href={`/blog/${Astro.props.previous}`}>Previous</a>}
- {next && <a href={`/blog/${Astro.props.next}`}>Next</a>}
- </div>
+ <main
+ itemprop="mainContentOfPage"
+ itemscope
+ itemtype="https://schema.org/WebPageElement"
+ >
+ <section
+ id="posts"
+ itemprop="citation"
+ itemscope
+ itemtype="http://schema.org/Blog"
+ >
+ <h2 itemprop="name description">{title}</h2>
+ <DateSelector {date} {years} {months} {days} />
+ {
+ (next || previous) && (
+ <nav>
+ {
+ previous && (
+ <p>
+ &lt; <a href={`/blog/${Astro.props.previous}`}>Anterior</a>
+ </p>
+ )
+ }
+ <span class="small">{format}</span>
+ {
+ next && (
+ <p><a href={`/blog/${Astro.props.next}`}>Próximo</a> &gt;</p>
+ )
+ }
+ </nav>
+ )
+ }
+ <SimplePostList
+ {posts}
+ dateOptions={{
+ weekday: "long",
+ year: "numeric",
+ month: "long",
+ day: "numeric",
+ hour: "2-digit",
+ minute: "2-digit",
+ timeZoneName: "long",
+ }}
+ />
+ {
+ (next || previous) && (
+ <nav>
+ {
+ previous && (
+ <p>
+ &lt; <a href={`/blog/${Astro.props.previous}`}>Anterior</a>
+ </p>
+ )
+ }
+ <span class="small">{format}</span>
+ {
+ next && (
+ <p><a href={`/blog/${Astro.props.next}`}>Próximo</a> &gt;</p>
+ )
+ }
+ </nav>
+ )
+ }
+ <DateSelector {date} {years} {months} {days} />
+ </section>
</main>
</Base>
+
+<style>
+ nav {
+ display: flex;
+ align-items: center;
+ padding-block: calc(var(--size-2) * 1em);
+ gap: calc(var(--size-2) * 1em);
+ justify-content: center;
+ & > p {
+ border-radius: calc(var(--size-0) * 1em);
+ border-width: 1px;
+ box-shadow: 0 1px 2px var(--color-light);
+ font-size: calc(var(--size-3) * 1rem);
+ font-weight: 500;
+ padding-inline: calc(var(--size-3) * 1em);
+ padding-block: calc(var(--size-2) * 1em);
+ display: inline-flex;
+ gap: calc(var(--size-2) * 1em);
+ align-items: center;
+ justify-content: center;
+ height: 2ch;
+ }
+ }
+</style>